#!/usr/bin/env python
# -*- coding: utf-8 -*-

import gtk
import gtk.glade
import datetime


import exputils
from expdb import ExpensesDatabase
import i18n

class GladeWidget(exputils.AbstractNotifier):
    def __init__(self, widget_name, widgets=[ ]):
        exputils.AbstractNotifier.__init__(self)
        
        self._xml = gtk.glade.XML('gui.glade', widget_name)
        
        #podłączenie sygnałów do funkcji
        self._xml.signal_autoconnect(self)
        
        #podłączenie uchwytów do widgetów
        for widget in widgets:
            self.__dict__[widget] = self._xml.get_widget(widget)
        
        #podłączenie uchwytu do głównego okna
        self._widget = self._xml.get_widget(widget_name)
    
    def _generate_event(self, sender):
        try:
            prefix, event =  sender.get_name().split('_', 1)
            self._notify_listeners(event)
        except IndexError:
            pass
    
    def set_config(self, data):
        pass
    
    def set_default_config(self):
        pass
    
    def get_config(self):
        return None
    


class GladeWindow(GladeWidget):
    def __init__(self, window_name, widgets = [ ]):
        GladeWidget.__init__(self, window_name, widgets)
        self._x, self._y = (0, 0)
    
    def is_visible(self):
        return self._widget.get_property('visible')
    
    def show(self):
        print 'showin at:', self._x, self._y
        self._widget.move(self._x, self._y)
        self._widget.show()
        self._widget.move(self._x, self._y)
    
    def hide(self):
        self._x, self._y = self._widget.get_position()
        print 'hidding at:', self._x, self._y
        self._widget.hide()

class TrayIcon(GladeWidget):
    def __init__(self, iconname=None, filename=None, tooltip=None):
        # utworzenie ikony w tray'u
        if iconname:
            self._icon = gtk.status_icon_new_from_icon_name(iconname)
        elif filename:
            self._icon = gtk.status_icon_new_from_file(filename)
        else:
            raise AttributeError()
        self._icon.set_tooltip(tooltip)
        self._icon.connect('activate', self.on_icon_clicked)
        self._icon.connect('popup-menu', self.on_icon_popup_menu)
        self._icon.set_visible(True)
        
        # utworzenie popup menu
        GladeWidget.__init__(self, 'status_menu')
    
    def on_icon_clicked(self, sender):
        self._notify_listeners('clicked')
    
    def on_icon_popup_menu(self, sender, button, activate_time):
        self._widget.popup(None, None, gtk.status_icon_position_menu, button, activate_time, sender)


class MainWindow(GladeWindow):
    def __init__(self):
        widgets = [ 'list', 'btn_today' ]
        GladeWindow.__init__(self, 'main_window', widgets)
        
        self._initialize_list()
    
    def _initialize_list(self):
        self.list_model = gtk.TreeStore(int, int, str, str)  # rowid:10, tag:1, value:2, description:3
        renderer_desc = gtk.CellRendererText()
        renderer_value = gtk.CellRendererText()
        column = gtk.TreeViewColumn('Saldo')
        column.pack_start(renderer_desc, True)
        column.pack_start(renderer_value, False)
        column.add_attribute(renderer_desc, 'markup', 3)    # opis
        column.add_attribute(renderer_value, 'markup', 2)   # wartość
        renderer_value.set_property('xalign', 1.0)
        self.list.append_column(column)
        self.list.set_model(self.list_model)
        self.expenses_node = self.list_model.append(None, (-1, -1, '', _('<b>Expenses:</b>')))
        self.earnings_node = self.list_model.append(None, (-1, -1, '', _('<b>Profits:</b>')))
    
    def get_selected_rowid(self):
        model, iter = self.list.get_selection().get_selected()
        if not iter or not model.iter_parent(iter):
            return None
        rowid = model.get_value(iter, 0)
        if rowid == -1:
            return None
        return rowid
    
    def _clear_node(self, node):
        while self.list_model.iter_has_child(node):
            child = self.list_model.iter_children(node)
            self.list_model.remove(child)
    
    def _fill_node(self, node, data, sum):
        for row in data:
            print row
            self.list_model.append(node, (row[0], row[3], '%.2f' % row[1], row[2]))
        if not self.list_model.iter_has_child(node):
            self.list_model.append(node, (-1, -1, '', 'Brak'))
        elif self.list_model.iter_n_children(node) > 1:
            self.list_model.append(node, (-1, -1, '<b>%.2f</b>' % sum, _('<b>Total:</b>')))
    
    def set_data(self, items, sums):
        self.list.set_model(None)
        self._clear_node(self.expenses_node)
        self._clear_node(self.earnings_node)
        
        self._fill_node(self.expenses_node, items[ExpensesDatabase.EXPENSE], sums[ExpensesDatabase.EXPENSE])
        self._fill_node(self.earnings_node, items[ExpensesDatabase.EARNING], sums[ExpensesDatabase.EARNING])
        
        self.list.set_model(self.list_model)
        self.list.expand_all()
    
    def set_day(self, day):
        self.btn_today.set_label(day)
    
    def on_close(self, sender, *args):
        self._notify_listeners('close')
        return True

    def get_config(self):
        config = { }
        config['position'] = (self._x, self._y)
        config['size'] = self._widget.get_size()
        return config

    def set_config(self, config):
        self._widget.resize(*config['size'])
        self._x, self._y = config['position']


class AddEditDialog(GladeWindow):
    def __init__(self):
        widgets = [ 'txt_value', 'txt_description', 'rbtn_outcome', 'rbtn_income', ]
        GladeWindow.__init__(self, 'ae_dialog', widgets)
    
    def on_close(self, sender, *args):
        gtk.main_quit()
        return True
    
    def on_ok_clicked(self, sender):
        dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK)
        if self.txt_value.get_value() <= 0:
            dlg.set_markup(_('Invalid value!'))
            dlg.run()
        elif self.txt_description.get_text() == '':
            dlg.set_markup(_('Description can\'t be empty!'))
            dlg.run()
        else:
            self._return_results = True
            gtk.main_quit()
        dlg.destroy()
    
    def on_cancel_clicked(self, sender):
        gtk.main_quit()
    
    def show_modal(self, title, data=None):
        # ustawienie tytułu okna dialogowego
        self._widget.set_title(title)
        # ustawienie danych
        if not data:    # wyczyszczenie pól wejściowych
            self.date = None
            self.txt_value.set_value(0)
            self.txt_description.set_text('')
            self.rbtn_outcome.set_active(True)
        else:           # wpisanie w pola podanych danych
            self.date = data[0]
            self.txt_value.set_value(abs(data[1]))
            self.txt_description.set_text(data[2])
            if data[3] == ExpensesDatabase.EXPENSE:
                self.rbtn_outcome.set_active(True)
            else:
                self.rbtn_income.set_active(True)
        self._return_results = False
        # wyświetlenie okna w trybie modalnym
        self.show()
        gtk.main()
        # ukrycie okna
        self.hide()
        # zwrócenie wpisanych danych
        if not self._return_results:
            return None
        else:
            value = self.txt_value.get_value()
            description = self.txt_description.get_text()
            if self.rbtn_outcome.get_active():
                type = ExpensesDatabase.EXPENSE
            else:
                type = ExpensesDatabase.EARNING
            return [value, description, type, None, self.date]
    
class MonthDialog(GladeWindow):
    def __init__(self):
        widgets = [ 'lbl_month', 'lbl_expenses', 'lbl_avg_expenses', 'lbl_earnings', 'lbl_saldo',
                    'btn_current_month', 'btn_current_year' ]
        GladeWindow.__init__(self, 'month_dialog', widgets)
    
    def on_prev_month(self, sender):
        month = self._date.month - 1
        year = self._date.year
        if month == 0:
            month = 12
            year -= 1
        d = datetime.date(year, month, 1)
        self.set_date(d)
    
    def on_next_month(self, sender):
        month = self._date.month + 1
        year = self._date.year
        if month == 13:
            month = 1
            year += 1
        d = datetime.date(year, month, 1)
        self.set_date(d)
    
    def on_prev_year(self, sender):
        d = datetime.date(self._date.year - 1, self._date.month, 1)
        self.set_date(d)
    
    def on_next_year(self, sender):
        d = datetime.date(self._date.year + 1, self._date.month, 1)
        self.set_date(d)
    
    def on_ok_clicked(self, sender):
        self.hide()
    
    def on_close(self, sender, *args):
        self.hide()
        return True
    
    def set_data(self, data):
        self.lbl_expenses.set_label(_('%.2f $') % data[ExpensesDatabase.EXPENSE]['sum'])
        self.lbl_avg_expenses.set_label(_('%.2f $') % data[ExpensesDatabase.EXPENSE]['avg'])
        self.lbl_earnings.set_label(_('%.2f $') % data[ExpensesDatabase.EARNING]['sum'])
        if data['total'] < 0:
            color = 'red'
        else:
            color = 'green'
        self.lbl_saldo.set_label('<span color="%s" weight="bold">%s</span>' % (color, _('%.2f $') % data['total']))
    
    def set_date(self, date):
        self._date = date
        self.btn_current_month.set_label(date.strftime('%B'))
        self.btn_current_year.set_label(date.strftime('%Y'))
        self._notify_listeners('date_changed', date)
        
    def show(self, date):
        self.set_date(date)
        GladeWindow.show(self)
    
    